//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.apache.hc.core5.http.impl.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.EndpointDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpMessage;
import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.impl.BasicEndpointDetails;
import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
import org.apache.hc.core5.http.io.BHttpConnection;
import org.apache.hc.core5.http.io.SessionInputBuffer;
import org.apache.hc.core5.http.io.SessionOutputBuffer;
import org.apache.hc.core5.http.io.entity.EmptyInputStream;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.io.Closer;
import org.apache.hc.core5.net.InetAddressUtils;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.Timeout;

class BHttpConnectionBase implements BHttpConnection {
    final Http1Config http1Config;
    final SessionInputBufferImpl inBuffer;
    final SessionOutputBufferImpl outbuffer;
    final BasicHttpConnectionMetrics connMetrics;
    final AtomicReference<SocketHolder> socketHolderRef;
    private byte[] chunkedRequestBuffer;
    volatile ProtocolVersion version;
    volatile EndpointDetails endpointDetails;

    BHttpConnectionBase(Http1Config http1Config, CharsetDecoder charDecoder, CharsetEncoder charEncoder) {
        this.http1Config = http1Config != null ? http1Config : Http1Config.DEFAULT;
        BasicHttpTransportMetrics inTransportMetrics = new BasicHttpTransportMetrics();
        BasicHttpTransportMetrics outTransportMetrics = new BasicHttpTransportMetrics();
        this.inBuffer = new SessionInputBufferImpl(inTransportMetrics, this.http1Config.getBufferSize(), -1, this.http1Config.getMaxLineLength(), charDecoder);
        this.outbuffer = new SessionOutputBufferImpl(outTransportMetrics, this.http1Config.getBufferSize(), this.http1Config.getChunkSizeHint(), charEncoder);
        this.connMetrics = new BasicHttpConnectionMetrics(inTransportMetrics, outTransportMetrics);
        this.socketHolderRef = new AtomicReference();
    }

    protected SocketHolder ensureOpen() throws IOException {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        if (socketHolder == null) {
            throw new ConnectionClosedException();
        } else {
            socketHolder.getSocket().setSoLinger(true,0);
            return socketHolder;
        }
    }

    protected void bind(Socket socket) throws IOException {
        Args.notNull(socket, "Socket");
        this.bind(new SocketHolder(socket));
    }

    protected void bind(SocketHolder socketHolder) throws IOException {
        Args.notNull(socketHolder, "Socket holder");
        this.socketHolderRef.set(socketHolder);
        this.endpointDetails = null;
    }

    public boolean isOpen() {
        return this.socketHolderRef.get() != null;
    }

    public ProtocolVersion getProtocolVersion() {
        return this.version;
    }

    protected SocketHolder getSocketHolder() {
        return (SocketHolder)this.socketHolderRef.get();
    }

    protected OutputStream createContentOutputStream(long len, SessionOutputBuffer buffer, OutputStream outputStream, Supplier<List<? extends Header>> trailers) {
        if (len >= 0L) {
            return new ContentLengthOutputStream(buffer, outputStream, len);
        } else {
            return (OutputStream)(len == -1L ? new ChunkedOutputStream(buffer, outputStream, this.getChunkedRequestBuffer(), trailers) : new IdentityOutputStream(buffer, outputStream));
        }
    }

    private byte[] getChunkedRequestBuffer() {
        if (this.chunkedRequestBuffer == null) {
            int chunkSizeHint = this.http1Config.getChunkSizeHint();
            this.chunkedRequestBuffer = new byte[chunkSizeHint > 0 ? chunkSizeHint : 8192];
        }

        return this.chunkedRequestBuffer;
    }

    protected InputStream createContentInputStream(long len, SessionInputBuffer buffer, InputStream inputStream) {
        if (len > 0L) {
            return new ContentLengthInputStream(buffer, inputStream, len);
        } else if (len == 0L) {
            return EmptyInputStream.INSTANCE;
        } else {
            return (InputStream)(len == -1L ? new ChunkedInputStream(buffer, inputStream, this.http1Config) : new IdentityInputStream(buffer, inputStream));
        }
    }

    HttpEntity createIncomingEntity(HttpMessage message, SessionInputBuffer inBuffer, InputStream inputStream, long len) {
        return new IncomingHttpEntity(this.createContentInputStream(len, inBuffer, inputStream), len >= 0L ? len : -1L, len == -1L, message.getFirstHeader("Content-Type"), message.getFirstHeader("Content-Encoding"));
    }

    public SocketAddress getRemoteAddress() {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        return socketHolder != null ? socketHolder.getSocket().getRemoteSocketAddress() : null;
    }

    public SocketAddress getLocalAddress() {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        return socketHolder != null ? socketHolder.getSocket().getLocalSocketAddress() : null;
    }

    public void setSocketTimeout(Timeout timeout) {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        if (socketHolder != null) {
            try {
                socketHolder.getSocket().setSoTimeout(Timeout.defaultsToDisabled(timeout).toMillisecondsIntBound());
            } catch (SocketException var4) {
            }
        }

    }

    public Timeout getSocketTimeout() {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        if (socketHolder != null) {
            try {
                return Timeout.ofMilliseconds((long)socketHolder.getSocket().getSoTimeout());
            } catch (SocketException var3) {
            }
        }

        return Timeout.DISABLED;
    }

    public void close(CloseMode closeMode) {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.getAndSet(null);
        if (socketHolder != null) {
            Socket socket = socketHolder.getSocket();

            try {
                if (closeMode == CloseMode.IMMEDIATE) {
                    socket.setSoLinger(true, 0);
                }
            } catch (IOException var8) {
            } finally {
                Closer.closeQuietly(socket);
            }
        }

    }

    public void close() throws IOException {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.getAndSet(null);
        if (socketHolder != null) {
            Socket socket = socketHolder.getSocket();
            Throwable var3 = null;

            try {
                this.inBuffer.clear();
                this.outbuffer.flush(socketHolder.getOutputStream());
            } catch (Throwable var12) {
                var3 = var12;
                throw var12;
            } finally {
                if (socket != null) {
                    if (var3 != null) {
                        try {
                            socket.close();
                        } catch (Throwable var11) {
                            var3.addSuppressed(var11);
                        }
                    } else {
                        socket.close();
                    }
                }

            }
        }

    }

    private int fillInputBuffer(Timeout timeout) throws IOException {
        SocketHolder socketHolder = this.ensureOpen();
        Socket socket = socketHolder.getSocket();
        int oldtimeout = socket.getSoTimeout();

        int var5;
        try {
            socket.setSoTimeout(timeout.toMillisecondsIntBound());
            var5 = this.inBuffer.fillBuffer(socketHolder.getInputStream());
        } finally {
            socket.setSoTimeout(oldtimeout);
        }

        return var5;
    }

    protected boolean awaitInput(Timeout timeout) throws IOException {
        if (this.inBuffer.hasBufferedData()) {
            return true;
        } else {
            this.fillInputBuffer(timeout);
            return this.inBuffer.hasBufferedData();
        }
    }

    public boolean isDataAvailable(Timeout timeout) throws IOException {
        this.ensureOpen();

        try {
            return this.awaitInput(timeout);
        } catch (SocketTimeoutException var3) {
            return false;
        }
    }

    public boolean isStale() throws IOException {
        if (!this.isOpen()) {
            return true;
        } else {
            try {
                int bytesRead = this.fillInputBuffer(Timeout.ofMilliseconds(1L));
                return bytesRead < 0;
            } catch (SocketTimeoutException var2) {
                return false;
            } catch (SocketException var3) {
                return true;
            }
        }
    }

    public void flush() throws IOException {
        SocketHolder socketHolder = this.ensureOpen();
        this.outbuffer.flush(socketHolder.getOutputStream());
    }

    protected void incrementRequestCount() {
        this.connMetrics.incrementRequestCount();
    }

    protected void incrementResponseCount() {
        this.connMetrics.incrementResponseCount();
    }

    public SSLSession getSSLSession() {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        if (socketHolder != null) {
            Socket socket = socketHolder.getSocket();
            return socket instanceof SSLSocket ? ((SSLSocket)socket).getSession() : null;
        } else {
            return null;
        }
    }

    public EndpointDetails getEndpointDetails() {
        if (this.endpointDetails == null) {
            SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
            if (socketHolder != null) {
                Socket socket = socketHolder.getSocket();

                Timeout socketTimeout;
                try {
                    socketTimeout = Timeout.ofMilliseconds((long)socket.getSoTimeout());
                } catch (SocketException var5) {
                    socketTimeout = Timeout.DISABLED;
                }

                this.endpointDetails = new BasicEndpointDetails(socket.getRemoteSocketAddress(), socket.getLocalSocketAddress(), this.connMetrics, socketTimeout);
            }
        }

        return this.endpointDetails;
    }

    public String toString() {
        SocketHolder socketHolder = (SocketHolder)this.socketHolderRef.get();
        if (socketHolder != null) {
            Socket socket = socketHolder.getSocket();
            StringBuilder buffer = new StringBuilder();
            SocketAddress remoteAddress = socket.getRemoteSocketAddress();
            SocketAddress localAddress = socket.getLocalSocketAddress();
            if (remoteAddress != null && localAddress != null) {
                InetAddressUtils.formatAddress(buffer, localAddress);
                buffer.append("<->");
                InetAddressUtils.formatAddress(buffer, remoteAddress);
            }

            return buffer.toString();
        } else {
            return "[Not bound]";
        }
    }
}
